home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 142
/
Gekkan Dennou Club - 2000.3 Vol. 142 (Japan).7z
/
Gekkan Dennou Club - 2000.3 Vol. 142 (Japan) (Track 1).bin
/
imelo
/
cmscc
/
cmscc.c
next >
Wrap
C/C++ Source or Header
|
2000-02-06
|
11KB
|
566 lines
/*
着メロコンパイラ@@
*.cms → 何等かのテキスト
*/
#include <stdio.h>
extern int CMSCC_conv23_F502i();
extern int CMSCC_conv23_P501i();
extern int CMSCC_conv23_HDGE_J80();
extern int CMSCC_conv23_SH811();
int Telephone; //電話機の種類
typedef enum{
F502I, //iMODE
P501I,
N501I, //@@まだ
D501I, //@@まだ
HDGE_J80, //H"(SANYO PHS-J80)
SH811 //ドッチーモ(SHARP SH811)
} TELEPHONE;
/*
共通設定項目
*/
int nowLen=4; //音長(デフォルト=4)
int nowOct=4; //オクターブ(デフォルト=4)
int nowKsignS=0,nowKsignF=0; //調号の設定
//0cdefgab
// +++++++--1=ON/0=OFF
#define BUFSIZE (256) //*.cms1行あたりのサイズ
unsigned char inBuf[BUFSIZE], //ファイル読み込みバッファ
tmpBuf[BUFSIZE*16], //1→2変換バッファ
outBuf[BUFSIZE*16], //2→3出力バッファ
mesBuf[BUFSIZE]; //エラーメッセージなど
const unsigned char *errMes[]={ //エラーメッセージいろいろ
NULL,
"Lnの値が異常です",
"Onの値が異常です"
};
enum {
noErr,
L_NUMBER_ERR,
O_NUMBER_ERR,
} errNum;
/*
Ln(有効n値:1,2,4.,4,8.,8,16)のチェックおよびnowLenの設定
res:s0を基準に、読み進めるカウント数(0以下でエラー)
*/
int L_Check(s0,s1,s2,s3)
unsigned char s0,s1,s2,s3; //s0=='L'の状態で呼び出される
{
int step=2;
short futen2=(s2=='.')?1:0;
switch( s1 ){
case '1':
if( s2=='6' ){
nowLen=16;
step=3;
}
else if( s2=='2' ){
nowLen=12;
step=3;
}
else{ //L1?の時は、Lでエラーとしない
nowLen=1;
}
break;
case '2': nowLen=2; break;
case '3': nowLen=3; break;
case '4': //符点4分かどうか
if( futen2 ){ nowLen=3; step++; }
else{ nowLen=4; }
break;
case '6': nowLen=6; break;
case '8': //符点8分かどうか
if( futen2 ){ nowLen=6; step++; }
else{ nowLen=8; }
break;
default:
step=-1;
break;
}
return(step);
}
/*
On(有効n値:3~5)のチェックおよびnowOctの設定
res:s0を基準に、読み進めるカウント数==2(0以下でエラー)
*/
int O_Check(s0,s1)
unsigned char s0,s1; //s0=='O'の状態で呼び出される
{
int step=2;
switch( s1 ){
case '3': case '4': case '5':
nowOct=s1-'0';
break;
default:
step=-1;
break;
}
return(step);
}
/*
MMLのチェック
outに変換後のMMLを入れる
出力形態は、
On?fl
|||+-音長('1','2','3','4','6','8',12='C',16='H')
||+--#フラグ('+'or'0'なし)
|+---音名('C','D','E','F','G','A','B'or'R')
+----オクターブ('3','4','5')
を一応。保証。
趣味の問題で、後ろに' '($20)を3ついれて、8バイト1組みにする
*/
int MML_Check(out,s0,s1,s2,s3)
unsigned char *out;
unsigned char s0,s1,s2,s3;
{
int step=0;
unsigned char *o=out;
char skip=0; //MML出力スキップする(1)/しない(0)/それ以外
unsigned char name=0; //音階
char sharp_flat=0; //#+(=+1)-(=-1)つきか
unsigned char len=0; //音長が指定されているか
unsigned char add[16];
unsigned char s[4],*sp;
s[0]=s0;s[1]=s1;s[2]=s2;s[3]=s3;
sp=s;
/* 解析
*/
switch( *sp ){
case 'c': case 'C':
case 'd': case 'D':
case 'e': case 'E':
case 'f': case 'F':
case 'g': case 'G':
case 'a': case 'A':
case 'b': case 'B':
switch( *(sp+1) ){
case '#': case '+': name=*sp++; sharp_flat=1; sp++; step++; goto skip_r; break;
case '-': name=*sp++; sharp_flat=-1; sp++; step++; goto skip_r; break;
}
case 'r': case 'R': //休符
name=*sp++;
skip_r:
step++;
if( *sp=='1' ){
if( *(sp+1)=='6' ){ len=16; step++; }
else if( *(sp+1)=='2' ){len=12; step++; }
else{ len=1; }
step++;
}
else if( *sp=='2' ){ len=2; step++; }
else if( *sp=='3' ){ len=3; step++; }
else if( *sp=='4' ){
if( *(sp+1)=='.' ){ len=3; step++; }
else{ len=4; }
step++;
}
else if( *sp=='6' ){ len=6; step++; }
else if( *sp=='8' ){
if( *(sp+1)=='.' ){ len=6; step++; }
else{ len=8; }
step++;
}
break;
case '<':
nowOct++;
skip=1;
step++;
if( 5<nowOct ){
step=-2;
goto quick_exit;
}
break;
case '>':
nowOct--;
skip=1;
step++;
if( nowOct<3 ){
step=-2;
goto quick_exit;
}
break;
/* 例外字スキップ関係
*/
case '@': //@@暫定「@n」のみ有効
skip=1;
step+=2;
break;
/* 空文字スキップ関係
*/
case ' ':
case 0x0d: case 0x0a: case '\t':/*改行系*/
skip=*sp;
step++;
break;
default:
step=-1;
goto quick_exit;
break;
}
/* 生成
*/
*o=NULL;
if( skip==0 ){
if( 'a'<=name )name-=0x20; //大文字化
if( sharp_flat==-1 ){
//レ♭→ド♯ な感じの変換
switch( name ){
case 'D': name='C'; break;
case 'E': name='D'; break;
case 'G': name='F'; break;
case 'A': name='G'; break;
case 'B': name='A'; break;
}
sharp_flat=1;
}
if( ((len)?len:nowLen)==16 ){
sprintf(add,"O%d%C%CH",nowOct,name,(sharp_flat==1)?'+':'0');
}
else if( ((len)?len:nowLen)==12 ){
sprintf(add,"O%d%C%CC",nowOct,name,(sharp_flat==1)?'+':'0');
}
else{
sprintf(add,"O%d%C%C%d",nowOct,name,(sharp_flat==1)?'+':'0',(len)?len:nowLen);
}
strcat(o,add);
strcat(o," "); //隙間埋め
}
else if( skip!=1 ){ //単純スキップでなければ
// *o++=skip;
*o++=NULL;
}
quick_exit:
return(step);
}
typedef enum{
NORMAL=0, //通常終了
READ_REMARK=1, //注釈行読み込み
READ_CRLF=2, //改行読み込み
} CONV12_RESULT;
/*
*.cms → 中間コードへ
res:
*/
int CMSCC_conv12(src,dest,err)
unsigned char *src, //*.cms行
*dest, //中間コード行
*err; //エラーメッセージ
{
int res=NORMAL,step=0;
short MUSHI=0; //()は無視する:1=無視最中/0=無視してない
unsigned char *s,*d,*e;
unsigned char s0,s1,s2,s3;
s=src;
d=dest; *d=NULL;
e=err;
//行頭注釈チェック
if( *s=='/' ){
res=READ_REMARK;
goto quick_exit;
}
//行頭改行チェック
if( *s==0x0d || *s==0x0a ){
res=READ_CRLF;
goto quick_exit;
}
while( *s ){
s0=*s;s1=*(s+1);s2=*(s+2);s3=*(s+3); //4バイト先行読み込み
//printf("[%c]",s0);
/*
特殊文字・制御文字チェック
*/
switch( s0 ){
/* ()内無視チェック
*/
case '(':
MUSHI=1; //無視開始
goto next;
break;
case ')':
if( MUSHI==1 ){
MUSHI=0; //無視解除
}
else{
/* @@未実装
'('がないのに')'を指定したエラー
*/
}
goto next;
break;
/* '/'以降注釈チェック
*/
case '/': //'/'以降の行は無視して終わる
res=NORMAL;
goto quick_exit;
break;
}
if( MUSHI==0 ){ ; switch( s0 ){
/*
共通設定のチェック
*/
/* 音長
*/
case 'l': case 'L':
step=L_Check(s0,s1,s2,s3);
if( step<0 ){
res=-L_NUMBER_ERR;
err=errMes[L_NUMBER_ERR];
goto quick_exit;
}
s+=(step-1);
break;
/* オクターブ
*/
case 'o': case 'O':
step=O_Check(s0,s1);
if( step<0 ){
res=-O_NUMBER_ERR;
err=errMes[O_NUMBER_ERR];
goto quick_exit;
}
s+=(step-1);
break;
/*
MMLの解釈
*/
default:{
unsigned char out[32]; //@@本当は8+1バイトでよい
step=MML_Check(out,s0,s1,s2,s3);
if( step>=0 ){
/* OK
*/
s+=(step-1);
strcat(d,out);
///**/printf("[%s]",out);
}
else{
/* ダメ
*/
res=-O_NUMBER_ERR; //@@暫定
err=errMes[O_NUMBER_ERR];
goto quick_exit;
}
}break;
}}
next:
s++;
}
quick_exit:
return(res);
}
/* チェック用カタカナ変換
位置合わせあり版
注意:おそらくこの仕様にそわない携帯電話はないと思うが、
1 2 3 ド レ ミ
4 5 6 ファ ソ ラ
7 8 9 シ
のみ有効
*/
int CMSCC_convKANA(src,dest,err)
unsigned char *src,*dest,*err;
{
unsigned char *s,*d,*e;
unsigned char name0,name1; //音名
unsigned char skip; //スキップコード
enum{
SCH_NAME, //音名('1'~'7')が出るまで探す
SCH_BOTM //入力区切り('>')が出るまで探す
} CND;
short cnd=SCH_NAME;
s=src;
d=dest; *d=NULL;
e=err;
while( *s ){
/* 読み込み
*/
skip=0;
name0=0;
if( cnd==SCH_NAME ){
switch( *s ){
case '1': name0='ト';name1='゙'; break;
case '2': name0='レ';name1=' '; break;
case '3': name0='ミ';name1=' '; break;
case '4': name0='フ';name1='ァ'; break;
case '5': name0='ソ';name1=' '; break;
case '6': name0='ラ';name1=' '; break;
case '7': name0='シ';name1=' '; break;
case ' ': case 0x0d: case 0x0a: case '\t':
skip=*s++;
break;
default:
skip=' ';s++;
break;
}
if( name0!=0 ){
*d++=name0;*d++=name1;
cnd=SCH_BOTM;
if( *(s+1)=='>' ){
cnd=SCH_NAME;
}
s+=2;
}
else{
*d++=skip;
}
}
else if( cnd==SCH_BOTM ){
if( *s=='>' ){
cnd=SCH_NAME;
}
s++;
*d++=' ';
}
}
*d++=NULL;
}
int FatalErr(e)
unsigned char *e;
{
printf("ERR:%s\n",e);
}
int main(argc,argv)
int argc;
char *argv[];
{
int res=0;
FILE *fp;
if( argc==1 ){
printf("X68k 着メロコンパイラ(評価版) v0.10 by 電魔団\shoryu 2000\n"
"usage : @>cmscc *.cms [option]\n"
"option: /F 対応機種をF502iに(デフォルト)\n"
" /P P501iに\n"
" /H PHS-J80(H\")に\n"
" /H SH811(ドッチーモ)に\n"
);
res=-1;
goto quick_exit;
}
Telephone=F502I; //デフォルトは作者が持っているもの
if( argc==3 ){
if( argv[2][0]=='-' || argv[2][0]=='/' ){ ; switch( argv[2][1] ){
case 'f': case 'F': Telephone=F502I; break;
case 'p': case 'P': Telephone=P501I; break;
case 'h': case 'H': Telephone=HDGE_J80; break;
case 's': case 'S': Telephone=SH811; break;
}}
}
fp=fopen(argv[1],"rt");
if( fp==NULL ){
printf("%sが見つかりません\n",argv[1]);
res=-1;
goto quick_exit;
}
while( feof(fp)==0 ){
fgets(inBuf,BUFSIZE,fp);
res=CMSCC_conv12(inBuf,tmpBuf,mesBuf);
if( res==READ_REMARK || res==READ_CRLF ){
//printf("$");
//読みとばしていい行を読んだ
continue;
}
if( res<0 ){
FatalErr(mesBuf);
break;
}
//printf("//%s\n",tmpBuf);
switch( Telephone ){
case F502I: res=CMSCC_conv23_F502i(tmpBuf,outBuf,mesBuf); break;
case P501I: res=CMSCC_conv23_P501i(tmpBuf,outBuf,mesBuf); break;
case HDGE_J80: res=CMSCC_conv23_HDGE_J80(tmpBuf,outBuf,mesBuf);break;
case SH811: res=CMSCC_conv23_SH811(tmpBuf,outBuf,mesBuf); break;
}
if( res<0 ){ FatalErr(mesBuf); break; }
printf("%s\n",outBuf);
CMSCC_convKANA(outBuf,tmpBuf,mesBuf);
printf("%s\n",tmpBuf);
}
fclose(fp);
quick_exit:
return(res);
}